package com.fast.orm.exec;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fast.orm.data.DataPackage;
import com.fast.orm.data.Expression;
import com.fast.orm.data.Where;
import com.fast.orm.jdbc.JdbcImpl;
import com.fast.orm.jdbc.MySqlUtil;
import com.fast.orm.many.AutoQueryInfo;
import com.fast.orm.utils.BeanConvertUtil;
import com.fast.orm.utils.page.PageInfo;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class SelectExecution<POJO> {

    private final DataPackage dataPackage;

    public SelectExecution(DataPackage dataPackage) {
        this.dataPackage = dataPackage;
    }

    /**
     * 通过主键查询数据
     * 如果设置逻辑删除,对逻辑删除的数据不进行操作
     *
     * @param primaryKeyValue 主键参数
     * @return 查询到的数据结果
     */
    public POJO findByPrimaryKey(Comparable<?> primaryKeyValue) {
        if (primaryKeyValue == null) {
            throw new RuntimeException(dataPackage.getTableMapper().getTableName() + ": 主键参数不能为空!!!");
        }
        dataPackage.addWhere(new DataPackage.ConditionData(dataPackage.getTableMapper().getPrimaryKeyField(), primaryKeyValue, DataPackage.Way.AND, Expression.Equal));
        return findOne();
    }

    /**
     * 通过查询条件查询一条数据
     *
     * @return 数据结果
     */
    public POJO findOne() {
        dataPackage.setLimitParam(1);
        MySqlUtil.limit(dataPackage);
        List<POJO> list = findAll();
        return list.size() > 0 ? list.get(0) : null;
    }

    /**
     * 通过查询条件查询所符合要求的所有数据
     *
     * @return 数据结果
     */
    public List<POJO> findAll() {
        List<JSONObject> select = JdbcImpl.select(dataPackage);
        if (CollUtil.isNotEmpty(select) && CollUtil.isNotEmpty(dataPackage.getReturnMapper().getAutoQueryInfoList())) {
            for (AutoQueryInfo info : dataPackage.getReturnMapper().getAutoQueryInfoList()) {
                autoQuery(select, info);
                if (CollUtil.isNotEmpty(info.getAutoQueryInfoList())) {
                    List<JSONObject> queryList = new ArrayList<>();
                    for (JSONObject jsonObject : select) {
                        Object val = jsonObject.get(info.getFieldName());
                        if (val == null) {
                            continue;
                        }
                        if (info.getCollectionType()) {
                            List<JSONObject> valJson = JSONArray.parseArray(JSONObject.toJSONString(val), JSONObject.class);
                            jsonObject.put(info.getFieldName(),valJson);
                            queryList.addAll(valJson);
                        }else {
                            JSONObject valJson = JSONObject.parseObject(JSONObject.toJSONString(val));
                            jsonObject.put(info.getFieldName(),valJson);
                            queryList.add(valJson);
                        }
                    }
                    for (AutoQueryInfo subquery : info.getAutoQueryInfoList()) {
                        autoQuery(queryList, subquery);
                    }
                }
            }
        }
        return JSONArray.parseArray(select.toString(), dataPackage.getReturnClass());
    }

    private void autoQuery(List<JSONObject> select, AutoQueryInfo info) {
        Set<Object> queryData = new HashSet<>();
        for (JSONObject data : select) {
            Object value = data.get(info.getTargetColumnName());
            if (value != null) {
                queryData.add(value);
            }
        }
        if (queryData.size() < 1) {
            return;
        }
        DataPackage relatedQuery = new DataPackage(info.getQueryTableMapper().getObjClass());
        relatedQuery.setField(info.getThisFieldName());
        new Where<>(relatedQuery, null).in(queryData);
        List<JSONObject> joinDataList = JdbcImpl.select(relatedQuery);
        BeanConvertUtil.joinMerge(select, joinDataList, info);
    }

    /**
     * 通过查询条件查询所符合要求的数据数量
     *
     * @return 查询到的数据条数
     */
    public Integer findCount() {
        Integer count = JdbcImpl.count(dataPackage);
        return count;
    }

    /**
     * 通过查询条件查询所符合要求的数据,并进行分页
     *
     * @param pageNum       页数
     * @param pageSize      每页条数
     * @param navigatePages 页面数量
     * @return 分页对象, 内包含分页信息和查询到的数据
     */
    public PageInfo<POJO> findPage(Integer pageNum, Integer pageSize, Integer navigatePages) {
        MySqlUtil.setPage(dataPackage, pageNum, pageSize, navigatePages);
        Integer count = findCount();
        if (count < 1) {
            return new PageInfo<>(0, pageNum, pageSize, new ArrayList<>(), navigatePages);
        }
        MySqlUtil.limit(dataPackage);
        List<POJO> all = findAll();
        return new PageInfo<>(count, pageNum, pageSize, all, navigatePages);
    }

    /**
     * 通过查询条件查询所符合要求的数据,并进行分页,默认9页
     *
     * @param pageNum  页数
     * @param pageSize 条数
     * @return 分页对象, 内包含分页信息和查询到的数据
     */
    public PageInfo<POJO> findPage(Integer pageNum, Integer pageSize) {
        return findPage(pageNum, pageSize, 9);
    }
}
